#include "simple_wifi_sta.h"
#include <esp_log.h>
#include <string.h>
#include "esp_wifi.h"
#include <esp_event.h>
#include "nvs_flash.h"
#include <nvs.h>
#include <esp_err.h>
#include <esp_smartconfig.h>
#include "lwip/ip_addr.h"
#include "PipeLine.h"

#define TAG "WIFI_TASK"

#define DEFAULT_SSID            "你的WIFI账号"
#define DEFAULT_PASSWORD        "你的WIFI密码"

QueueHandle_t wifi_notification_queue;
EventGroupHandle_t s_wifi_event_group;
#define SMART_CONFIG_DONE_BIT   BIT0

static int connection_fail_count = 0;

// 事件处理函数
static void wifi_event_handler(void* arg, esp_event_base_t event_base, int32_t event_id, void* event_data)
{
    if (event_base == WIFI_EVENT && event_id == WIFI_EVENT_STA_START)
    {
        esp_wifi_connect();
    }
    else if (event_base == WIFI_EVENT && event_id == WIFI_EVENT_STA_DISCONNECTED)
    {
        ESP_LOGE(TAG, "WiFi disconnected, reason: %d", *((uint8_t*)event_data));
        connection_fail_count++;

        if (connection_fail_count >= 5)
        {
            ESP_LOGE(TAG, "Failed to connect 5 times, giving up");
            connection_fail_count = 0;

            xEventGroupSetBits(xEventGroup, WIFI_CONNECTED_BIT);  // 连接失败后设置标志位

            return; //计数达到5次后退出，放弃连接
        }

        vTaskDelay(pdMS_TO_TICKS(5000)); // 延迟5秒后重试
        esp_wifi_connect();
    }
    else if (event_base == IP_EVENT && event_id == IP_EVENT_STA_GOT_IP)
    {
        ip_event_got_ip_t* event = (ip_event_got_ip_t*)event_data;
        ESP_LOGI(TAG, "Got IP: " IPSTR, IP2STR(&event->ip_info.ip));
        ESP_LOGI(TAG,"get ip address");

        connection_fail_count = 0;

        xEventGroupSetBits(xEventGroup, WIFI_CONNECTED_BIT);  // 连接失败后设置标志位

    }
    else if (event_base == SC_EVENT && event_id == SC_EVENT_GOT_SSID_PSWD)
    {
        smartconfig_event_got_ssid_pswd_t *evt = (smartconfig_event_got_ssid_pswd_t *)event_data;
        wifi_config_t wifi_config = {
            .sta = {
                .ssid = {0},
                .password = {0},
                .scan_method = WIFI_FAST_SCAN,
                .bssid_set = 0,
                .channel = 0,
                .listen_interval = 3,
                .sort_method = WIFI_CONNECT_AP_BY_SIGNAL,
                .threshold.authmode = WIFI_AUTH_WPA2_PSK,
            }
        };
        memcpy(wifi_config.sta.ssid, evt->ssid, sizeof(wifi_config.sta.ssid));
        memcpy(wifi_config.sta.password, evt->password, sizeof(wifi_config.sta.password));

        ESP_LOGI(TAG, "New SSID: %s", evt->ssid);
        ESP_LOGI(TAG, "New Password: %s", evt->password);

        esp_wifi_disconnect();
        esp_wifi_set_config(WIFI_IF_STA, &wifi_config);
        vTaskDelay(pdMS_TO_TICKS(100));
        esp_wifi_connect();
    }
    else if (event_base == SC_EVENT && event_id == SC_EVENT_SEND_ACK_DONE)
    {
        esp_smartconfig_stop();
        xEventGroupSetBits(s_wifi_event_group, SMART_CONFIG_DONE_BIT);
    }
}

// 定义一个任务函数，该函数用于处理Wi-Fi相关操作
void wifi_task(void* pvParameters)
{
    // 定义一个字符变量，用于接收队列中的消息
    char cRxedChar;
	// 创建默认的事件循环
    esp_event_loop_create_default();
	
	// 注册WIFI事件
    esp_event_handler_register(WIFI_EVENT, ESP_EVENT_ANY_ID, &wifi_event_handler, NULL);
    esp_event_handler_register(IP_EVENT, IP_EVENT_STA_GOT_IP, &wifi_event_handler, NULL);
    esp_event_handler_register(SC_EVENT, ESP_EVENT_ANY_ID, &wifi_event_handler, NULL);

    // 初始化非易失性存储（NVS）Flash，用于存储Wi-Fi配置等信息
    nvs_flash_init();
    // 创建一个队列，用于接收Wi-Fi通知，队列长度为10，每个消息大小为char类型
    wifi_notification_queue = xQueueCreate(10, sizeof(char));
    // 创建一个事件组，用于管理Wi-Fi事件的状态
    s_wifi_event_group = xEventGroupCreate();

    // 初始化Wi-Fi配置
    wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT();
    esp_wifi_init(&cfg);
    esp_netif_init();
    esp_netif_create_default_wifi_sta();
    esp_wifi_set_mode(WIFI_MODE_STA);

    // 定义STA模式下的Wi-Fi配置项
    wifi_config_t wifi_config = {
        .sta = {
            .ssid = DEFAULT_SSID,                   // Wi-Fi的SSID
            .password = DEFAULT_PASSWORD,           // Wi-Fi的密码
            .scan_method = WIFI_FAST_SCAN,          // 扫描方法，快速扫描
            .bssid_set = 0,                         // 是否设置BSSID，0表示不设置
            .channel = 0,                         // 信道，0表示自动选择
            .listen_interval = 3,                   // 监听间隔，单位为AP的 beacon interval
            .sort_method = WIFI_CONNECT_AP_BY_SIGNAL, // 连接AP的方式，按信号强度排序
            .threshold.authmode = WIFI_AUTH_WPA2_PSK, // 认证模式，WPA2 PSK
        }
    };
    // 设置Wi-Fi配置
    esp_wifi_set_config(WIFI_IF_STA, &wifi_config);
    // 启动Wi-Fi驱动
    esp_wifi_start();

    // 任务循环，持续处理Wi-Fi任务
    while (1)
    {
        // 从队列中接收消息，如果队列为空，则任务阻塞直到有消息到达
        if (xQueueReceive(wifi_notification_queue, &cRxedChar, portMAX_DELAY))
        {
            // 如果接收到的消息是'S'，则开始SmartConfig流程
            if (cRxedChar == 'S')
            {
                // 获取当前Wi-Fi模式，确保为STA模式
                wifi_mode_t mode;
                esp_wifi_get_mode(&mode);
                if (mode != WIFI_MODE_STA)
                {
                    ESP_LOGE(TAG, "WiFi not in STA mode"); // 记录错误日志，Wi-Fi不在STA模式
                    continue;
                }
                // 设置SmartConfig类型为ESPTOUCH
                esp_smartconfig_set_type(SC_TYPE_ESPTOUCH);
                // 使用默认配置开始SmartConfig
                smartconfig_start_config_t sc_config = SMARTCONFIG_START_CONFIG_DEFAULT();
                esp_smartconfig_start(&sc_config);
                // 等待SmartConfig完成事件，最长等待10秒
                EventBits_t uxBits = xEventGroupWaitBits(s_wifi_event_group, SMART_CONFIG_DONE_BIT, pdTRUE, pdFALSE, pdMS_TO_TICKS(10000));
                if (uxBits & SMART_CONFIG_DONE_BIT)
                {
                    ESP_LOGI(TAG, "SmartConfig completed"); // 记录信息日志，SmartConfig完成
                }
                else
                {
                    ESP_LOGW(TAG, "SmartConfig timeout"); // 记录警告日志，SmartConfig超时
                }
            }
            // 如果接收到的消息是'R'，则重新连接Wi-Fi网络
            else if (cRxedChar == 'R')
            {
                // 断开当前Wi-Fi连接
                esp_wifi_disconnect();
                // 重新设置Wi-Fi配置
                esp_wifi_set_config(WIFI_IF_STA, &wifi_config);
                // 延时100毫秒
                vTaskDelay(pdMS_TO_TICKS(100));
                // 重新连接Wi-Fi网络
                esp_wifi_connect();
            }
        }

        // 任务延时，避免占用过多CPU资源
        vTaskDelay(pdMS_TO_TICKS(500));
    }
}


